import math
import nltk
import pickle

# Class that contains sax data for Saxifying.
class SaxData:
  def __init__(self, num_data, window, num_alpha, ztable_file = './ztable.txt'):
    # Calculate Standard deviation and average.
    num_sum = 0;
    num_sum_of_squares = 0
    len_num_data = len(num_data)
    for i in range(0, len_num_data-window+1):
      piece_avg = float(sum(num_data[i:i+window])) / float(window)
      num_sum += piece_avg
      num_sum_of_squares += piece_avg * piece_avg

    self.avg = float(num_sum)/float(len_num_data-window+1)
    self.sdev = math.sqrt(float(num_sum_of_squares) /
        float(len_num_data-window+1) - (self.avg * self.avg))

    # Save the zscore table
    self.ztable = open(ztable_file, 'r').readlines() 
    self.start_x_val = -3.4
    self.x_step = 0.01
    ztable_len = len(self.ztable)

    # Calculate the interval points according to number of characters.
    skip = ztable_len / num_alpha
    self.interval_points = [float(self.ztable[i]) for i in range(
        0, ztable_len, skip)] 
    self.interval_points.append(1.000)
    self.alphabets = [chr(ord('a')+i) for i in range(0, len(self.interval_points))] 

  #def set_alphabet_size(self, n):
  #  # Calculate the interval points according to number of characters.
  #  ztable_len = len(self.ztable)
  #  skip = ztable_len / n
  #  self.interval_points = [float(self.ztable[i]) for i in range(
  #      0, ztable_len, skip)] 
  #  self.interval_points.append(1.000)
  #  self.alphabets = [chr(ord('a')+i) for i in range(0, len(self.interval_points))] 

# Class that aids in discretizing using SAX.
class Saxer:
  def __init__(self, sax_model_file = None):
    if sax_model_file:
      self.sax_data = pickle.load(open(sax_model_file, 'r'))

  # Return the Zscore given the x value.
  def __zscore(self, val):
    x_val = self.sax_data.start_x_val
    zscore = 0.0
    for i in range(0, len(self.sax_data.ztable)):
      if val < x_val:
        break
      x_val += self.sax_data.x_step
      zscore = float(self.sax_data.ztable[i])
    return zscore 

  # Return the sax alphabet given the x value.
  def __saxify(self, num):
    normalized_val = (float(num) - float(self.sax_data.avg)) / float(self.sax_data.sdev)
    zscore = self.__zscore(normalized_val)
    char = 'a'
    for k in range(0, len(self.sax_data.interval_points)):
      if zscore < self.sax_data.interval_points[k]:
        break
      char = self.sax_data.alphabets[k]
    return char

  def saxify_value(self, num):
    return self.__saxify(num)

  # Return a list of sax alphabets for the num_data with moving average
  # of sax_gram
  def saxify(self, num_data):
    saxified_data = [self.__saxify(float(num_data[i]
          )) for i in range(0, len(num_data))]
    return saxified_data
